package com.dimaidt.workflow.TestActiviti;

import org.activiti.engine.*;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.DeploymentBuilder;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.apache.commons.lang3.builder.ToStringExclude;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.io.InputStream;
import java.util.List;
import java.util.zip.ZipInputStream;


@RunWith(SpringRunner.class)
@SpringBootTest
public class TestActi {


  /**
   * 用于测试创建的工作流
   * 影响到3个表的数据:
   * 1,act_ge_bytearray
   * 2,act_re_deployment
   * 3,act_re_procdef
   */
  @Test
  public void createActi(){
    //1.创建ProcessEngine对象
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

    //2.得到RepositoryService实例
    RepositoryService repositoryService = processEngine.getRepositoryService();

    //3.进行部署
    Deployment deployment = repositoryService.createDeployment()//创建Deployment对象
        .addClasspathResource("processes/holyday.bpmn")//添加bpmn文件
        .addClasspathResource("processes/holyday.png")//添加png文件
        .name("请假申请单流程")

        .deploy();//部署

    //4.输出部署的一些信息
    System.out.println(deployment.getName());
    System.out.println(deployment.getId());

  }


  /**
   * 运行流程的定义，影响到5个表的数据
   * `act_hi_actinst`
   * `act_hi_procinst`
   * `act_hi_taskinst`
   * `act_ru_execution`
   * `act_ru_task`
   */
  @Test
  public void runActi(){
    ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
    RuntimeService runtimeService = defaultProcessEngine.getRuntimeService();
    ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("myProcess_1");//这里对应的就是 act_re_procdef 表中的 KEY_ 字段内容
//    runtimeService.startProcessInstanceById("");


    //获取部署的ID号
    String deploymentId = processInstance.getDeploymentId();
    //获取部署的名称
    String name = processInstance.getName();
    //实例ID
    String id = processInstance.getId();
    //获取活动ID
    String activityId = processInstance.getActivityId();
    //获取部署时候的ID信息
    String processDefinitionId = processInstance.getProcessDefinitionId();

    System.out.println("流程部署ID deploymentId:" + deploymentId);
    System.out.println("流程实例ID id:" + id);
    System.out.println("流程活动ID activityId:" + activityId);
    System.out.println("流程活动name  name:" + name);
    System.out.println("流程活动定义的  processDefinitionId:" + processDefinitionId);

  }


  /**
   * 主管审批：也就是 zhangsan 开始查询和审批
   *  个人用户的查询
   */
  @Test
  public void taskQuery(){
    String assignee="zhangsan";
    ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
    TaskService taskService = defaultProcessEngine.getTaskService();

    //查询当前主管为 zhangsan 的审批事件
    List<Task> list = taskService.createTaskQuery()
        .processDefinitionKey("myProcess_1")
        .taskAssignee(assignee)
        .list();



    //任务列表展示
    for (Task task:list) {
      System.out.println("流程实例ID: "+ task.getProcessDefinitionId());
      System.out.println("任务ID: " + task.getId());
      System.out.println("当前审批人: " + task.getAssignee());
      System.out.println("任务名称: " + task.getName());
    }
  }


  /**
   * 主管为 zhangsan 的人，点击审批事件
   */
  @Test
  public void taskComplete(){

//    流程实例ID: myProcess_1:1:e30320fd-b91b-11ea-a502-00ff3cffc80a
//    任务ID: e5552752-b91b-11ea-a502-00ff3cffc80a
//    当前审批人: zhangsan
//    任务名称: 主管审批
    ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
    TaskService taskService = defaultProcessEngine.getTaskService();

    //1, 使用业务逻辑，查询 zhangsan 的审批数据，
    //2, 在zahngsan 的登录操作界面中，允许他审批
    taskService.complete("e5552752-b91b-11ea-a502-00ff3cffc80a");  //填入 任务ID




  }


  /**
   * 通过zip数据流的形式加载到activiti中
   */
  @Test
  public void createActiZip(){

    ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();

    RepositoryService repositoryService = defaultProcessEngine.getRepositoryService();

    //加载一个InputStream 的数据流
//    InputStream inputStream = TestActi.class.getResourceAsStream("./processes/holyday.zip");

    InputStream inputStream = TestActi.class.getClassLoader().getResourceAsStream("./processes/holyday.zip");


    System.out.println("intpStream: " + inputStream);

    ZipInputStream zipInputStream = new ZipInputStream(inputStream);

    Deployment deployment = repositoryService.createDeployment()
        .addZipInputStream(zipInputStream)
//        .key("myholydays_002")
        .name("请假申请流程4")
        .deploy();

    System.out.println("获得到的ID:" + deployment.getId());
    System.out.println("获得到的NAME:" + deployment.getName());
    System.out.println("获得到的getKey:" + deployment.getKey());
    System.out.println("获得到的key getTenantId:" + deployment.getTenantId());

  }




  //当创建完成之后，如何查询流程定义的信息
  @Test
  public void queryProcessDefinitions(){
    //1,获取得到ProcessEngine
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

    //2,创建ResponseService流程
    RepositoryService repositoryService = processEngine.getRepositoryService();

    //3,得到ProcessDefinitionQuery
    ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();


    //4,设置条件，查询出所有的流程定义信息,   key="myProcess_003"
    List<ProcessDefinition> list = processDefinitionQuery.processDefinitionKey("myProcess_003")
        .orderByProcessDefinitionVersion()  //根据版本号排序
        .desc() //逆序 .asc升序
        .list();// 查询所有列表


    //5,输出流程的定义信息
    for (ProcessDefinition item : list) {
      System.out.println("流程定义的ID:" + item.getId());
      System.out.println("流程定义的名称:" + item.getName());
      System.out.println("流程定义的KEY:" + item.getKey());
      System.out.println("流程定义的版本号:" + item.getVersion());
      System.out.println("流程定义的部署ID:" + item.getDeploymentId());


    }

  }



  //删除部署的定义
  @Test
  public void deteleDeplomentId(){
    ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
    RepositoryService repositoryService = defaultProcessEngine.getRepositoryService();
    repositoryService.deleteDeployment("b1ff8df5-c459-11ea-8812-00ff3cffc80a"); //根据deploymentId删除部署的定义数据  ，这里如果默认没有启动流程实例，那可以删除。如果已经启动了流程实例，已经有部分的审批完成了，那这个方法不行

    //需要强制删除的情况，用下面这种: 可以级联删除，不管启动不启动流程实例，不管是否有部分审批已经完成
//    repositoryService.deleteDeployment("b1ff8df5-c459-11ea-8812-00ff3cffc80a",true);

  }




  //业务场景：
  /**
   * 1,用户想查看自己提交的审批流程一共有几个步骤，那咋办？
   * 解决方式：
   *  通常，用户要查看，点击的时候，就从数据库表  act_ge_bytearray  中读取出来bpmn和png文件，放到服务器的某个路径下。用户查看的时候
   *  直接放回生成的文件即可
   *
   */
  @Test
  public void queryBpmnFile(){
    //1,获取得到ProcessEngine
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

    //2,创建ResponseService流程
    RepositoryService repositoryService = processEngine.getRepositoryService();

    //3,得到ProcessDefinitionQuery
    ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();


    //4,设置条件，查询出所有的流程定义信息,   key="myProcess_003"
    List<ProcessDefinition> list = processDefinitionQuery.processDefinitionKey("myProcess_003")
        .orderByProcessDefinitionVersion()  //根据版本号排序
        .desc() //逆序 .asc升序
        .list();// 查询所有列表


    //5,输出流程的定义信息
    for (ProcessDefinition item : list) {
      System.out.println("流程定义的ID:" + item.getId());
      System.out.println("流程定义的名称:" + item.getName());
      System.out.println("流程定义的KEY:" + item.getKey());
      System.out.println("流程定义的版本号:" + item.getVersion());
      System.out.println("流程定义的部署ID:" + item.getDeploymentId());
    }

    //6 通过查询DeplomentId得到部署的ID信息

    //7,通过repositoryService方法，实现读取BPMN和png图片文件的读取

    //8,构建输出outputStream流

    //9 输入流，输出流的转换

    //10输入流，输出流的关闭

  }


}
